package com.jbh.netlibrary.u;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.os.Handler;
import android.util.Log;
import androidx.core.net.ConnectivityManagerCompat;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class DeviceNetUtil {


    private DeviceNetUtil() {

    }

    /**
     * 检查当前WIFI是否连接，两层意思——是否连接，连接是不是WIFI
     *
     * @param context
     * @return true表示当前网络处于连接状态，且是WIFI，否则返回false
     */
    public static boolean isWifiConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.isConnected() && ConnectivityManager.TYPE_WIFI == info.getType()) {
            return true;
        }
        return false;
    }

    /**
     * 检查当前GPRS是否连接，两层意思——是否连接，连接是不是GPRS
     *
     * @param context
     * @return true表示当前网络处于连接状态，且是GPRS，否则返回false
     */
    public static boolean isGprsConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.isConnected() && ConnectivityManager.TYPE_MOBILE == info.getType()) {
            return true;
        }
        return false;
    }

    /**
     * 检查当前是否连接
     *
     * @param context
     * @return true表示当前网络处于连接状态，否则返回false
     */
    public static boolean isConnected(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            return true;
        }
        return false;
    }

    /**
     * 对大数据传输时，需要调用该方法做出判断，如果流量敏感，应该提示用户
     *
     * @param context
     * @return true表示流量敏感，false表示不敏感
     */
    public static boolean isActiveNetworkMetered(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return ConnectivityManagerCompat.isActiveNetworkMetered(cm);
    }


    public static Intent registerReceiver(Context context, ConnectivityChangeReceiver receiver) {
        return context.registerReceiver(receiver, ConnectivityChangeReceiver.FILTER);
    }

    public static void unregisterReceiver(Context context, ConnectivityChangeReceiver receiver) {
        context.unregisterReceiver(receiver);
    }


    /**
     * 检测是否连接
     */
    public static void checkConnected(final Context context, final com.jbh.netlibrary.i.Callback<Integer> callback) {
        try {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            NetworkInfo gprsInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            NetworkCapabilities nc = null;

            boolean wifiConnected = false;
            boolean gprsConnected = false;

            if (wifiInfo != null && wifiInfo.isConnected()) {
                wifiConnected = true;
            }

            if (gprsInfo != null && gprsInfo.isConnected()) {
                gprsConnected = true;
            }
            // 1 、网络已连接但是检测是否具备上网能力
            if (wifiConnected || gprsConnected) {
                get("https://time.taojinapp.com:8220/time?t=" + System.currentTimeMillis(), new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        new Handler(context.getMainLooper())
                                .post(new Runnable() {
                                    @Override
                                    public void run() {
                                        callback.onState(-1);
                                    }
                                });
                        Log.v("net_api", "[checkViaHttpRequest] - > 2 ");
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        new Handler(context.getMainLooper())
                                .post(new Runnable() {
                                    @Override
                                    public void run() {
                                        callback.onState(0);
                                    }
                                });
                        Log.v("net_api", "[checkViaHttpRequest] - > 1 ");
                    }
                });
            }


            // 2、判断是否是Disconnected
            boolean wifiDisconnected = false;
            boolean gprsDisconnected = false;
            if (wifiInfo == null || wifiInfo.getState() == State.DISCONNECTED) {
                wifiDisconnected = true;
            }
            if (gprsInfo == null || gprsInfo.getState() == State.DISCONNECTED) {
                gprsDisconnected = true;
            }
            if (wifiDisconnected && gprsDisconnected) {
                callback.onState(-1);
            }
        } catch (Exception e) {
            Log.v("net_api", "[net] - > " + "DeviceNetUtil ConnectivityChangeReceiver->onReceive->" + e.getMessage());
            callback.onState(-1);
        }
    }


    public static abstract class ConnectivityChangeReceiver extends BroadcastReceiver {

        public static final IntentFilter FILTER = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);

        @Override
        public final void onReceive(final Context context, Intent intent) {
            checkConnected(context, new com.jbh.netlibrary.i.Callback<Integer>() {
                @Override
                public void onState(final Integer integer) {
                    new Handler(context.getMainLooper())
                            .post(new Runnable() {
                                @Override
                                public void run() {
                                    if (integer == 0) {
                                        onConnected();
                                    } else {
                                        onDisconnected();
                                    }
                                }
                            });

                }
            });
        }

        protected abstract void onDisconnected();

        protected abstract void onConnected();
    }


    /**
     * 是否具备上网的能力
     *
     * @return
     */
    public static boolean isInternetAvailable() {
        try {
            Process process = Runtime.getRuntime().exec("ping -c 1 www.baidu.com");
            int exitValue = process.waitFor();
            return (exitValue == 0);
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 验证网络请求
     *
     * @param url
     * @param timeoutMs
     * @return
     */
    public static boolean checkViaHttpRequest(String url, int timeoutMs) {
        try {
            URL connectionUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) connectionUrl.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(timeoutMs);
            conn.connect();
            boolean b = (conn.getResponseCode() == 200);

            return b;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 方式四
     * <p>
     * 使用OKHttp 实现网络请求
     */
    public static void get(String api, Callback callBack) {
        /*okHttp*/
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.MINUTES)
                .readTimeout(20, TimeUnit.MINUTES)
                .build();
        /*请求动作*/
        Request request = new Request.Builder()
                .url(api)
                .addHeader("Content-type", "application/json")
                .get()
                .build();
        /*异步相应的结果*/
        client.newCall(request).enqueue(callBack);
    }
}